import { getQueryParam, IData, QueryParamKeys } from '@amcax/base';
import { MessageTip } from '@app-cad/common/utils/MessageTip';
import { omitBy } from 'lodash';
import { Vector3Tuple } from 'three-legacy';
import { nmAppErrorLog } from '../common/utils';
import { showLoading } from '../components';
import {
  ICollection,
  IComponent,
  IDocument,
  IMeshControl,
  IMeshSeed,
  IMeshSize,
  IResult,
  ISimulation,
  ISimulationPlugin,
  ITask,
} from '../types';
import { GspEngine } from './GspEngine';

export class DocumentV2 {
  static async getEngine() {
    const documentId = getQueryParam<string>(QueryParamKeys.DOCUMENT_ID);
    const documentVersion = getQueryParam<string>(QueryParamKeys.VERSION);
    return await GspEngine.connect(documentId, documentVersion);
  }

  static async execCmd(
    params,
    showLoad?: boolean,
    returnFullResponse?: boolean,
  ) {
    const gspEngine = await DocumentV2.getEngine();
    const hide = showLoad ? showLoading() : null;
    return gspEngine
      .execCmd(
        omitBy(params, (v) => v == null),
        returnFullResponse,
      )
      .catch((error) => {
        nmAppErrorLog('DocumentV2.execCmd', error);
        MessageTip.error(`命令执行失败：${error?.message}`);

        throw error;
      })
      .finally(() => {
        hide?.();
      });
  }

  /**
   * 加载文档信息：打开websocket连接后调用一次；从CAD切换到CAE调用一次。
   */
  async load() {
    return await DocumentV2.execCmd({ c: 'document.load' });
  }

  /**
   * 获取文档的信息
   * @returns 文档信息
   */
  async get(): Promise<IDocument> {
    return await DocumentV2.execCmd({ c: 'document.info' });
  }

  /**
   * 同步文档，在CAD文档更新后，调用该接口更新component等
   */
  async sync() {
    return await DocumentV2.execCmd({ c: 'document.sync' });
  }

  /**
   * 添加component
   * @param a 参数键值对，比如： {name: 'xxx', ...}
   * @returns 添加后的component，包含uuid等
   */
  async addComponent(a: IComponent) {
    return await DocumentV2.execCmd(
      {
        c: 'component.add',
        a,
      },
      true,
    );
  }

  /**
   * 更新component
   * @param a 参数键值对，比如： {name: 'xxx', ...}
   * @returns 更新后的component，包含uuid、更新时间等
   */
  async updateComponent(a: IComponent) {
    return await DocumentV2.execCmd(
      {
        c: 'component.update',
        a,
      },
      true,
    );
  }

  /**
   * 删除component
   * @param uuid component uuid
   * @returns 空对象：{}
   */
  async deleteComponent(uuid: string) {
    return await DocumentV2.execCmd(
      {
        c: 'component.delete',
        a: { uuid },
      },
      true,
    );
  }

  async autoMesh() {
    return await DocumentV2.execCmd(
      {
        c: 'mesh.autoMesh',
      },
      true,
    );
  }

  async generateMesh(
    type: 'lineMesh' | 'general2D' | 'tetMesh',
    data: IMeshSize,
  ) {
    return await DocumentV2.execCmd(
      {
        c: `mesh.${type}`,
        a: { MeshSize: [data] },
      },
      true,
    );
  }

  async lineMesh(d: IMeshSeed): Promise<Vector3Tuple[]> {
    return await DocumentV2.execCmd(
      {
        c: 'mesh.lineMesh',
        a: d,
      },
      true,
    );
  }

  /**
   * Seed网格生成点坐标数组在前端渲染
   * @param d 网格Seed参数
   */
  async seedMesh(d: IMeshSeed): Promise<Vector3Tuple[]> {
    return await DocumentV2.execCmd(
      {
        c: 'mesh.seed',
        a: d,
      },
      true,
    );
  }

  async updateMeshControl(d: IMeshControl) {
    return await DocumentV2.execCmd(
      {
        c: 'mesh.updateControl',
        ...d,
      },
      true,
    );
  }

  async deleteMesh(meshIds: string[]) {
    return await DocumentV2.execCmd(
      {
        c: 'mesh.delete',
        a: meshIds,
      },
      true,
    );
  }

  /**
   * 更新集合信息
   * @param data 集合信息
   * @returns
   */
  async updateCollections(data: ICollection[]) {
    return await DocumentV2.execCmd({ c: 'collections.update', data }, true);
  }

  /**
   * 获取生成细网格的渲染数据
   * @param uuid 网格uuid
   */
  async getVisualMesh2(): Promise<IData[]> {
    return await DocumentV2.execCmd({
      c: 'mesh.renderData',
    });
  }

  async listMeshQuality() {
    return await DocumentV2.execCmd({
      c: 'tool.listQuality',
    });
  }

  async updateMeshQuality(d: any) {
    return await DocumentV2.execCmd({
      c: 'tool.updateQuality',
      ...d,
    });
  }

  async queryMeshQuality(d: any) {
    return await DocumentV2.execCmd(
      {
        c: 'tool.queryQuality',
        ...d,
      },
      true,
    );
  }

  async addSimulation(d: ISimulation) {
    return await DocumentV2.execCmd({
      c: 'simulation.add',
      ...d,
    });
  }

  async updateSimulation(d: ISimulation) {
    return await DocumentV2.execCmd({
      c: 'simulation.update',
      ...d,
    });
  }

  async deleteSimulation(uuid: string) {
    return await DocumentV2.execCmd({
      c: 'simulation.delete',
      uuid,
    });
  }

  async listSimulationPlugins(): Promise<ISimulationPlugin[]> {
    return await DocumentV2.execCmd({
      c: 'simulation.listPlugins',
    });
  }

  /**
   * 删除结果
   * @param uuid 结果uuid
   * @returns
   */
  async deleteResult(uuid: string) {
    return await DocumentV2.execCmd({
      c: 'result.delete',
      uuid,
    });
  }

  /**
   * 获取结果列表
   * @returns
   */
  async listResults(): Promise<IResult[]> {
    return await DocumentV2.execCmd({
      c: 'result.list',
    });
  }

  async resultInfo(uuid: string): Promise<IResult> {
    return await DocumentV2.execCmd({
      c: 'result.info',
      uuid,
    });
  }

  async resultData(uuid: string, params: any) {
    return await DocumentV2.execCmd({
      c: 'result.data',
      uuid,
      ...params,
    });
  }

  async resultRenderData(uuid: string): Promise<IData[]> {
    return await DocumentV2.execCmd({
      c: 'result.renderData',
      uuid,
    });
  }

  async addPostprocess(d: any) {
    return await DocumentV2.execCmd({
      c: 'postprocess.add',
      ...d,
    });
  }

  async updatePostprocess(d: any) {
    return await DocumentV2.execCmd({
      c: 'postprocess.update',
      ...d,
    });
  }

  async deletePostprocess(uuid: string) {
    return await DocumentV2.execCmd({
      c: 'postprocess.delete',
      uuid,
    });
  }

  async generatePostporeccess(uuid: string, params: any) {
    return await DocumentV2.execCmd({
      c: 'postprocess.renderData',
      uuid,
      ...params,
    });
  }

  async getPostRenderDeform(uuid: string, params: any) {
    return await DocumentV2.execCmd({
      c: 'postprocess.renderDeform',
      uuid,
      ...params,
    });
  }

  async getPostRenderISOSurface(uuid: string, params: any) {
    return await DocumentV2.execCmd({
      c: 'postprocess.renderISOSurface',
      uuid,
      ...params,
    });
  }

  /**
   * 获取生成成功的网格列表、执行成功的仿真列表
   * @returns
   */
  async getSources() {
    return await DocumentV2.execCmd({ c: 'document.listSources' });
  }

  // 获取张量图相关的数据
  async renderTensor(uuid: string, params: any): Promise<any> {
    return await DocumentV2.execCmd({
      c: 'postprocess.renderTensor',
      uuid,
      ...params,
    });
  }

  // 获取向图相关的数据
  async renderVector(uuid: string, params: any): Promise<any> {
    return await DocumentV2.execCmd({
      c: 'postprocess.renderVector',
      uuid,
      ...params,
    });
  }

  /**
   * 获取任务状态列表信息
   * @returns 任务列表
   */
  // TODO 多个调用的地方，应该共用一份数据
  async listTasks(): Promise<ITask[]> {
    return await DocumentV2.execCmd({ c: 'task.list' });
  }

  /**
   * 获取仿真任务的 monitor file content，用于任务结束后
   * @returns 残差图/日志监控数据
   */
  async getTaskMonitorData(uuid: string) {
    return await DocumentV2.execCmd({ c: 'task.monitorData', uuid });
  }

  /**
   * 添加任务
   */
  async addTask(data: any): Promise<ITask> {
    return await DocumentV2.execCmd({ c: 'task.add', ...data });
  }

  /**
   * 更新任务
   */
  async updateTask(data: any) {
    return await DocumentV2.execCmd({ c: 'task.update', ...data });
  }

  /**
   * 执行任务
   */
  async executeTask(uuid: string) {
    return await DocumentV2.execCmd({ c: 'task.execute', uuid });
  }

  /**
   * 取消执行任务
   */
  async cancelTask(uuid: string) {
    return await DocumentV2.execCmd({ c: 'task.cancel', uuid });
  }

  /**
   * 删除任务
   */
  async deleteTask(uuid: string) {
    return await DocumentV2.execCmd({ c: 'task.delete', uuid });
  }

  // Start 几何清理API
  async import(path: string) {
    return await DocumentV2.execCmd({
      c: 'standard.importData',
      t: path,
    });
  }
  async export(path: string) {
    return await DocumentV2.execCmd({
      c: 'standard.exportData',
      t: path,
    });
  }
  // E几何清理API
  // 几何清理
  //  插入点
  /**
   *
   * @param params 插入点的参数
   * @param isPreview 是否预览
   * @returns
   */
  async insertPoint(params: any, isPreview: boolean = false) {
    return await DocumentV2.execCmd({
      c: 'geometry.insert',
      a: params,
      p: isPreview,
    });
  }
  /**
   *
   * @param params 插入点的参数
   * @param isPreview 是否预览
   * @returns
   */
  async intersectPoint(params: any, isPreview: boolean = false) {
    return await DocumentV2.execCmd({
      c: 'geometry.intersect',
      a: params,
      p: isPreview,
    });
  }
  /**
   *
   * @param params 投影点的参数
   * @param isPreview 是否预览
   * @returns
   */
  async projectPoint(params: any, isPreview: boolean = false) {
    return await DocumentV2.execCmd({
      c: 'geometry.project',
      a: {
        ...params,
      },
      p: isPreview,
    });
  }
  async deleteEntity(params: { mode: string; source: string[] }) {
    return await DocumentV2.execCmd({
      c: 'geometry.deleteEntity',
      a: {
        ...params,
      },
    });
  }

  async releaseEntity(ids: string[]) {
    return await DocumentV2.execCmd({
      c: 'geometry.release',
      a: {
        source: ids,
      },
    });
  }
  async getRenderData(objectIds: Array<string>) {
    return await DocumentV2.execCmd({
      c: 'geometry.renderData',
      a: {
        objectIds: objectIds,
      },
    });
  }
  async fillHole(params: Array<string>, isPreview = false) {
    return await DocumentV2.execCmd({
      c: 'geometry.fillHole',
      a: params,
      p: isPreview,
    });
  }
  async query(params: { source: string }) {
    return await DocumentV2.execCmd({
      c: 'geometry.query',
      a: params,
    });
  }
  async generateEntity(params: any, isPreview: boolean = false) {
    return await DocumentV2.execCmd({
      c: 'geometry.generate',
      a: {
        ...params,
      },
      p: isPreview,
    });
  }
  // 变换
  async transform(
    params: {
      mode: string;
      source: string[];
      relyOn: (string | number)[][];
      param?: number[];
    },
    isPreview = false,
  ) {
    return await DocumentV2.execCmd({
      c: 'geometry.transform',
      a: params,
      p: isPreview,
    });
  }
  // 去特征
  async defeature(params: { target: string[]; param: number[] }) {
    return await DocumentV2.execCmd({
      c: 'geometry.defeature',
      a: params,
    });
  }
  // 切分
  async trim(params: { mode: string; target: string[]; relyOn: string[] }) {
    return await DocumentV2.execCmd({
      c: 'geometry.trim',
      a: params,
    });
  }
  // 抽中面
  async midsurface(params: { target: string[]; param: number }) {
    return await DocumentV2.execCmd({
      c: 'geometry.midsurface',
      a: params,
    });
  }
  async modifyEntity(
    param: { mode: string; source: string[]; target: string[] },
    isPreview: boolean = true,
  ) {
    return await DocumentV2.execCmd({
      c: 'geometry.modify',
      a: param,
      p: isPreview,
    });
  }
  async mergeEntity(
    param: { mode: string; source: string[]; target?: string[] },
    isPreview: boolean = false,
  ) {
    return await DocumentV2.execCmd({
      c: 'geometry.merge',
      a: param,
      p: isPreview,
    });
  }
  // 基础线形
  async basicCurve(
    params: {
      source?: string[] | Vector3Tuple[];
      param?: number[];
      mode: 'segment' | 'curve' | 'ellipse' | 'rectangle' | 'circle';
    },
    isPreview = false,
  ) {
    return await DocumentV2.execCmd({
      c: 'geometry.basicCurve',
      a: params,
      p: isPreview,
    });
  }
  // 基础面形
  async basicPlaneShape(
    params: { source: number[][]; param?: number[] },
    isPreview: boolean = false,
  ) {
    return await DocumentV2.execCmd({
      c: 'geometry.geometry.basicSurface',
      a: {
        ...params,
      },
      p: isPreview,
    });
  }
  // 开孔
  async drillHole(
    params: { target: string[]; source: number[] },
    param: number[],
  ) {
    return await DocumentV2.execCmd({
      c: 'geometry.drillHole',
      a: {
        ...params,
        param,
      },
    });
  }
}
